local ManageBase = require("app.base.ManageBase")
local InfoManager = require ("app.info.InfoManager.lua"):GetInstance()

local ActorManage = class("ActorManage",ManageBase)
ActorManage.instance = nil

local SOLDIERS = 1
local HERO = 2
local BUILDING = 3

local ActorBaseList ={
    [SOLDIERS] = "app.actor.SoldiersBase",
    [HERO] = "app.actor.HeroBase",
    [BUILDING] = "app.actor.BuildingBase",
}

function ActorManage:ctor()
    ActorManage.super.ctor(self)
    self.name = "ActorManage"
    self.ActorList = {}
    self.actorId = 0
    self.ActorInfo = InfoManager:GetRole()
end

function ActorManage:GetInstance()
	if ActorManage.instance == nil then
		ActorManage.instance = ActorManage.new()
	end
	return ActorManage.instance
end

--function ActorManage:newActor(name,data)
--    local path = "app.actor."..name
--    local _actor = require(path).new(data)
----    table.insert(self.ActorList, _actor)
--    self:AddActor(_actor)
----    self.actorId = self.actorId + 1
----    _actor.id = self.actorId
----    self.ActorList[_actor.id] = _actor
--    return _actor
--end

function ActorManage:newActor(id,data)
    local path = clone(self.ActorInfo[id])
    for name, var in pairs(data) do
        path[name] = var
    end
    
    local _actor = require(ActorBaseList[path.career]).new(path)
    self:AddActor(_actor)
    return _actor
end

function ActorManage:AddActor(_actor)
    self.actorId = self.actorId + 1
    _actor.id = self.actorId
    self.ActorList[_actor.id] = _actor
--    for i, var in ipairs(self.ActorList) do
--        print("i="..i.." id="..var.id)
--    end
end

function ActorManage:DeleteActor(id)
    if self.ActorList[id] then 
--        self.ActorList[id]:DeleteSelf()
        self.ActorList[id]=nil
    end
end

function ActorManage:Update(dt)
    for id, actor in pairs(self.ActorList) do
        actor:Update(dt)
    end   
--    self:CollisionExclude()
end

function ActorManage:CollisionExclude()
    local ActorTable = td.MapLayer:GetActorTable()
    local GetMapTable = td.MapLayer:GetMapTable()
    --    dump(ActorsForPos)
    for _, actorMap in ipairs(ActorTable) do        -- 遍历所有的Actor
        --        dump(actorMap)
        local thisActor = actorMap.actor        -- 获取当前actor        
        local actorIdList = { }
        for _, occupy in ipairs(actorMap.grid) do            -- 遍历每个actor占据(occupy)的格子坐标数组
            local _actorIdList = GetMapTable[occupy.x][occupy.y]            -- 通过坐标获取该格子内的所有actorID ,的list
            for _, var in ipairs(_actorIdList) do
                table.insert(actorIdList,var )
            end    
        end
        local otherActor = { } --即将发生的斥力相关全部存储在这里
        for _, actorId in ipairs(actorIdList) do            -- 并且遍历这个actorList
            local _actor = self:GetActor(actorId)
            if thisActor.id ~= _actor.id then                -- 不和自己做碰撞判定
                for caseNum=0,1 do    --进行不同级别的斥力判定，已经碰撞和即将碰撞
                        if otherActor.level == nil or otherActor.level >= caseNum then  --有碰撞不做绕行
                        local this_pos = thisActor:pos()    --可节约
                        local this_shift = cc.pMul(thisActor.shift,caseNum)
                        local this_posAdd = cc.pAdd(this_pos,this_shift)                    
                        local delta = cc.pDistanceSQ(this_posAdd,_actor:pos())
                        local R = thisActor:radius() + _actor:radius()
                        if  delta < R*R then
                            if otherActor.range == nil or R*R - delta > otherActor.range then
                                -- 每一次只做最近的推挤
                                otherActor.actor = _actor
                                otherActor.delta = delta
                                otherActor.range = R*R - delta
                                otherActor.R = R
                                otherActor.level = caseNum
                            end
                        end 
                    end
                end
            end
        end
        if otherActor.actor then
            if otherActor.level == 0 then --直接碰撞直接推挤
                local UnitVector = cc.pNormalize(cc.pSub(thisActor:pos(),otherActor.actor:pos()))
                local Range = ( otherActor.R*1.01 - math.sqrt(otherActor.delta) )*0.5
                local pow = cc.pMul(cc.pMul(UnitVector,Range),otherActor.actor:weight())

                local coefficient
                if thisActor:weight() >= otherActor.actor:weight() * 2 then
                    coefficient = 0
                elseif thisActor:weight() <= otherActor.actor:weight() *0.5 then
                    coefficient = 1
                else
                    coefficient = 0.5
                end
                local pow_m = cc.pMul(pow , coefficient)
                local pow_p = cc.pSub(pow_m,pow)
                thisActor:SavePow(pow_m,2)
                otherActor.actor:SavePow(pow_p,2)
            elseif otherActor.level == 1 then --即将碰撞则法线推挤（绕行）  

                local c_pos = td.PointSlopeForm( { a_pos = thisActor:pos(), b_pos = otherActor.actor:pos(), a_k = thisActor.shift })
                local Range =  otherActor.R -- math.sqrt(otherActor.delta) )*1
                local roundLength = cc.pGetDistance(otherActor.actor:pos(), c_pos) 

                local UnitVector

                if roundLength <= 0.1 * Range then                    -- 直指圆心的时候
                    --                            print(thisActor.id.."我绕开")
                    roundLength = 0.1 * Range
                    local roundDelta =(math.abs(thisActor.id - otherActor.actor.id) % 2 - 0.5) * 2
                    UnitVector = cc.pNormalize(thisActor:pos(), c_pos)
                    UnitVector.x, UnitVector.y = - UnitVector.x * roundDelta, UnitVector.y * roundDelta
                else                    -- 有偏差时
                    --                            print(thisActor.id.."我绕开中")
                    UnitVector = cc.pNormalize(cc.pSub(c_pos,otherActor.actor:pos()))
                end

                local coefficient =(Range - roundLength) / Range -- * caseNum --cc.pGetLength(this_shift)                        -- 基于距离的绕行推挤系数

                local pow = cc.pMul(cc.pMul(UnitVector,coefficient),otherActor.actor:weight())
                thisActor:SavePow(pow,1)
            end
        end
    end
end

function ActorManage:GetActor(id)
    if id then 
        return self.ActorList[id]
    end
    return self.ActorList 
end


return ActorManage
